﻿#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <iostream>
#include <unordered_map>
#include <queue>
#include <memory>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <thread>
#include <chrono>

/* Any 类型
 * 可以接收任意数据的类型
 */
class Any
{
public:
	Any() = default;
	~Any() = default;

	/* 成员变量 unique_ptr 应当禁止拷贝 */
	Any(const Any &) = delete;
	Any &operator=(const Any &) = delete;
	
	/* 提供移动构造 */
	Any(Any &&) = default;
	Any &operator=(Any &&) = default;

	template <typename T>
	Any(T data) : base_(std::make_unique<Derive<T>>(data)) {}

	/* 将 Any 对象存储的数据提取
	 * 转换失败：Derive<T> 与 cast_<T>() 不匹配
	 */
	template <typename T>
	T cast_() const
	{
		/* 基类指针 -> 派生类指针 */
		Derive<T> *derive_ptr = dynamic_cast<Derive<T> *>(base_.get());
		if (derive_ptr == nullptr)
		{
			std::cerr << "type is unmatched!" << std::endl;
			throw std::bad_cast();
		}

		return derive_ptr->data_;
	}

private:
	/* 基类类型 */
	class Base
	{
	public:
		virtual ~Base() = default;
	};

	/* 派生类型 */
	template <typename T>
	class Derive : public Base
	{
	public:
		Derive(T data) : data_(data) {}

		T data_; // 保存任意其他类型
	};

private:
	std::unique_ptr<Base> base_; // 基类指针实现多态
};

/* 信号量类 */
class Semaphore
{
public:
	Semaphore(size_t limit = 0) : resourceLimit_(limit)
	{
	}

	~Semaphore() = default;

	/* 获取一个信号量资源 */
	void wait()
	{
		std::unique_lock<std::mutex> lock(mtx_);
		cond_.wait(lock, [&]() -> bool
				   { return resourceLimit_ > 0; });
		resourceLimit_--;
	}

	/* 释放一个信号量资源 */
	void signal()
	{
		std::unique_lock<std::mutex> lock(mtx_);
		cond_.notify_all();
		resourceLimit_++;
	}

private:
	size_t resourceLimit_;
	std::mutex mtx_;
	std::condition_variable cond_;
};

/* 任务抽象基类
 * 用户可以自定义任意任务类型，从Task继承，重写 run 方法实现自定义任务处理
 * run 方法返回可以接收任意数据的类型 Any
 */
class Result;
class Task
{
public:
	Task() : result_ptr_(nullptr) {}
	virtual ~Task() = default;

	/* 用户自定义任务处理方法 */
	virtual Any run() = 0;

	/* 对 run 方法进行功能扩展 */
	void exec();

	/* 绑定任务的返回结果到 Result */
	void setResult(Result *res);

private:
	Result *result_ptr_; // 将 Task 与 Result 组合
};

/* 任务执行完成的返回值 */
class Result
{
public:
	Result() = default;
	~Result() = default;

	Result(std::shared_ptr<Task> task_ptr, bool isValid = true);

	/* 获取任务执行完成的返回值
	 */
	void setValue(Any any);

	/* 获取 task 的返回值
	 * 阻塞当前线程直到获取返回值
	 * 用户调用
	 */
	Any getResult();

private:
	Any any_;						 // 存储任务的返回值
	Semaphore sem_;					 // 线程通信信号量
	std::shared_ptr<Task> task_ptr_; // 指向任务对象，用于获取返回值
	std::atomic_bool isValid_;		 // 任务返回值是否有效
};

/* 线程池工作模式 */
enum class PoolMode
{
	MODE_FIXED,	 // 固定数量的线程
	MODE_CACHED, // 线程数量可以动态增长
};

/* 线程类型 */
class Thread
{
public:
	using ThreadFunc = std::function<void(size_t)>; // 线程函数对象类型

	Thread(ThreadFunc func);
	~Thread() = default;

	size_t getThreadId() const;

private:
	ThreadFunc func_;
	static size_t generateId_; // 手动生成
	size_t threadId_;		   // 线程自定义编号
};

/* 线程池类型 */
class ThreadPool
{
public:
	ThreadPool();
	~ThreadPool();

	/* 设置线程池的工作模式 */
	void setMode(PoolMode mode);

	/* 设置 task 任务队列上限阈值 */
	void setTaskQueMaxThreshHold(size_t threshHold);

	/* 设置线程池 cached 模式下线程阈值 */
	void setThreadSizeThreshHold(size_t threshHold);

	/* 给线程池提交任务 - 生产者 */
	Result submitTask(std::shared_ptr<Task> sp);

	/* 开启线程池 */
	void start(size_t initThreadSize = std::thread::hardware_concurrency());

	/* 禁止拷贝构造 */
	ThreadPool(const ThreadPool &) = delete;
	ThreadPool &operator=(const ThreadPool &) = delete;

private:
	/* 定义线程函数
	 * 从任务队列里面消费任务 - 消费者
	 */
	void threadFunc(size_t threadId);

private:
	std::atomic_bool isPoolRunning_;
	PoolMode poolMode_; // 当前线程池的工作模式

	/* 线程列表 */
	std::unordered_map<size_t, std::unique_ptr<Thread>> threads_; // 使用智能指针保证任务对象的生命周期
	size_t initThreadSize_;										  // 初始线程数量
	size_t threadSizeThreshHold_;								  // 线程数量上限
	std::atomic_uint64_t idleThreadSize_;						  // 记录空闲线程数量

	/* 任务队列 */
	std::queue<std::shared_ptr<Task>> tasksQue_; // 使用智能指针保证任务对象的生命周期
	std::atomic_uint64_t tasksSize_;			 // 任务数量
	size_t tasksQueMaxThreshHold_;				 // 任务队列数量上限

	std::mutex tasksQueMtx_;		   // 保证任务队列线程安全
	std::condition_variable notFull_;  // 任务队列不满
	std::condition_variable notEmpty_; // 任务队列不空

	std::condition_variable exitCond_; // 等待线程池资源全部回收

	/* 检查线程池运行状态
	 * `true`: 运行中
	 */
	bool checkPoolState() const;
};

#endif